package moon.core.classdef;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;

import moon.core.Model;
import moon.core.Name;
import moon.core.NamedObject;
import moon.core.genericity.FormalPar;

/**
 * Type in the model.
 * 
 * @author <a href="mailto:rmartico@ubu.es">Ra&uacute;l Marticorena</a>
 * @since JavaMoon-2.0
 */
@SuppressWarnings("serial")
public abstract class Type extends NamedObject{
	
	/**
	 * Constructor.
	 * 
	 * @param name name
	 */
	public Type(Name name) {
		super(name);
	}
	
	/**
	 * Gets the class that generates this type.
	 * 
	 * @return class generator class
	 */
	public abstract ClassDef getClassDef();
	
	
	/**
	 * Reference type.
	 * 
	 * @return true if the type is a type reference, false in other case
	 */
	public abstract boolean isReference();
	
	/**
	 * Complete type.
	 * 
	 * @return true if it is complete, false in other case
	 */
	public abstract boolean isComplete();
	
	/**
	 * Parametric type.
	 * 
	 * @return true if it is a parametric type.
	 */
	public abstract boolean isParametricType();
	
    /**
     * Gets the type code.
     * 
     * @return type code
     */
    public abstract String getTypeCode();
    
    /**
     * Check if it a subtype.
     */
    public abstract boolean isSubtype(Type type);
    
    /**
     * Gets the formal par related to the type. 
     * If the type is complete, i.e.String, List<String> the list is empty. 
     * If the type is a formal par i.e. E, the list contains only the formal parameter. i.e. E
     * if the type is not complete i.e. List<E>, Map<K,V> the list contains [E], [K,V]
	 *
     * @return list of formal parameters
     */
    public abstract List<FormalPar> getRelatedFormalParameters();

    
    /**
     * Gets transformed type. From an initial type obtains a new type
     * on the basis of current type. Can be used as a filter
     * or chain to transform types.
     * 
     * @param type initial type
     * @return transformed type
     */
    public abstract Type getTransformedType(Type type);
    
    
    /**
     * Gets the calculated type of replacing the formal parameter with the
     * type in current type.
     * 
     * @param type new type 
     * @param formalPar formal parameter 
     * @param model model
     * @return type replacing formal parameter with new type.
     */
    public abstract Type calculateType(Type type, FormalPar formalPar, Model model);
    
    /**
     * Calculates the substitutions of formal parameters with types in current
     * type.
     * 
     * @return pairs of formal parameters and their substitutions
     */
    public abstract SortedMap<FormalPar, Type> calculateSubstitutions();
    
    
    
} // Type
